use crate::ProcTreeNode;

pub struct PrintOpt {
    pub sort: bool,
    pub show_pid: bool,
}

fn node_to_string(node: &ProcTreeNode, opt: &PrintOpt) -> String {
    if opt.show_pid {
        format!("{}({})", &node.name, node.pid)
    } else {
        node.name.clone()
    }
}

fn print_node(node: &ProcTreeNode, opt: &PrintOpt, prefix: &str) {
    let node_str = node_to_string(node, opt);
    print!("{}", &node_str);

    let cur_prefix = format!("{}{}", prefix, " ".repeat(node_str.len() + 1));
    let next_prefix = format!("{}{} ", cur_prefix, "│");
    let last_next_prefix = format!("{}  ", cur_prefix);

    let mut subs: Vec<&ProcTreeNode> = node.subs.iter().collect();
    let sub_len = subs.len();
    if opt.sort {
        subs.sort_unstable_by_key(|n| n.pid)
    };
    for (i, n) in subs.iter().enumerate() {
        if i == 0 {
            if sub_len == 1 {
                print!("{}", "───");
            } else {
                print!("{}", "─┬─");
            }
        } else if i == sub_len - 1 {
            print!("\n{}{}", &cur_prefix, "└─");
        } else {
            print!("\n{}{}", &cur_prefix, "├─");
        }
        if i != sub_len - 1 {
            print_node(n, opt, &next_prefix);
        } else {
            print_node(n, opt, &last_next_prefix);
        }
    }
}

pub fn print_proc_tree(root: &ProcTreeNode, opt: &PrintOpt) {
    print_node(root, opt, "");
    print!("\n");
}
